#pragma once
#include <pthread.h>
#include <iostream>
#include <functional>
#include <queue>
#include <typeinfo>
using namespace std;
template <typename Req, typename Rsp>
class thread_pool_t
{
private:
    // 单例模式
    thread_pool_t(function<void(Req &, Rsp &)> call_back = function<void(Req &, Rsp &)>(), size_t thread_num = 6)
        : _service_func(call_back), _thread_num(thread_num), _is_running(false), _req_queue(), _rsp_queue()
    {
        pthread_mutex_init(&_rsp_queue_mutex, nullptr);
        pthread_mutex_init(&_req_queue_mutex, nullptr);
        pthread_cond_init(&_task_condition, nullptr);
        pthread_cond_init(&_result_condition, nullptr);
    }
    thread_pool_t(thread_pool_t<Req, Rsp> &thread_pool) = delete;
    // operator =(thread_pool_t<Req,Rsp>&thread_pool)=delete;//用赋值重载构造对象,会被转换成构造/拷贝构造(都不成立)
public:
    static thread_pool_t<Req, Rsp> *get_thread_pool_instance(function<void(Req &, Rsp &)> call_back = function<void(Req &, Rsp &)>(), int thread_num = 6)
    {
        if (_this)
            return _this;
        else
        {
            // 单例本身也是临界资源
            static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
            pthread_mutex_lock(&mutex);
            if (_this == nullptr)
                _this = new thread_pool_t<Req, Rsp>(call_back, thread_num);
            pthread_mutex_unlock(&mutex);
        }
        return _this;
    }
    // 专用于垃圾回收的内部类
    struct thread_pool_recycler_t
    {
        ~thread_pool_recycler_t()
        {
            delete _this;
        }
    };
    ~thread_pool_t()
    {
        pthread_mutex_destroy(&_req_queue_mutex);
        pthread_cond_destroy(&_task_condition);
    }

public:
    bool start()
    {
        if (!_is_running)
        {
            create_thread();
            return true;
        }
        cerr << "Already started!" << endl;
        return false;
    }
    // 接收任务
    void put_req(Req &request)
    {
        pthread_mutex_lock(&_req_queue_mutex);
        {
            _req_queue.push(request);
        }
        pthread_mutex_unlock(&_req_queue_mutex);
        assign_task();
    }
    // 右值版本
    void put_req(Req &&request)
    {
        pthread_mutex_lock(&_req_queue_mutex);
        {
            _req_queue.push(request);
        }
        pthread_mutex_unlock(&_req_queue_mutex);
        assign_task();
    }
    // 输出结果
    void get_rsp(Rsp &response)
    {
        pthread_mutex_lock(&_rsp_queue_mutex);
        {
            while (!have_result())
            {
                pthread_cond_wait(&_result_condition, &_rsp_queue_mutex);
            }
            response = _rsp_queue.front();
            _rsp_queue.pop();
        }
        pthread_mutex_unlock(&_rsp_queue_mutex);
    }

private:
    bool have_task() { return !_req_queue.empty(); }
    bool have_result() { return !_rsp_queue.empty(); }
    // 唤醒等待的线程
    void assign_task() { pthread_cond_signal(&_task_condition); }
    void assign_result() { pthread_cond_signal(&_result_condition); }
    // 线程获取任务
    void get_req(Req &req)
    {
        // 临界区 临界资源:req_queue 变量:_task_condition 互斥锁: _req_queue_mutuex
        {
            pthread_mutex_lock(&_req_queue_mutex);
            {
                // 没有任务就利用条件变量释放锁等待指派任务
                while (!have_task())
                {
                    pthread_cond_wait(&_task_condition, &_req_queue_mutex);
                }
                req = _req_queue.front();
                _req_queue.pop();
            }
            pthread_mutex_unlock(&_req_queue_mutex);
        }
    }
    // 线程放置执行结果
    void put_rsp(Rsp &rsp)
    {
        // 临界区 临界资源:rsp_queue 变量:_result_condition 互斥锁: _rsp_queue_mutuex
        {
            pthread_mutex_lock(&_rsp_queue_mutex);
            {
                _rsp_queue.push(rsp);
            }
            pthread_mutex_unlock(&_rsp_queue_mutex);
        }
        // 唤醒等待执行结果的执行流
        assign_result();
    }
    // 右值版本
    void put_rsp(Rsp &&rsp)
    {
        // 临界区 临界资源:rsp_queue 变量:_result_condition 互斥锁: _rsp_queue_mutuex
        {
            pthread_mutex_lock(&_rsp_queue_mutex);
            {
                _rsp_queue.push(rsp);
            }
            pthread_mutex_unlock(&_rsp_queue_mutex);
        }
        // 唤醒等待执行结果的执行
        assign_result();
    }

    static void *thread_routine(void *argc)
    {
        pthread_detach(pthread_self());
        thread_pool_t *p_this = static_cast<thread_pool_t *>(argc);
        while (1)
        {
            // 获取任务
            Req req = Req();
            p_this->get_req(req);
            // 执行任务
            Rsp rsp = Rsp();
            p_this->_service_func(req, rsp);
            // 放结果
            p_this->put_rsp(rsp);
        }
        return nullptr;
    }
    void create_thread()
    {
        for (int i = 0; i < _thread_num; i++)
        {
            pthread_t tid;
            pthread_create(&tid, nullptr, thread_routine, static_cast<void *>(this));
        }
    }

private:
    bool _is_running;
    size_t _thread_num;
    function<void(Req &, Rsp &)> _service_func;
    queue<Req> _req_queue;
    queue<Rsp> _rsp_queue;
    pthread_mutex_t _rsp_queue_mutex;
    pthread_mutex_t _req_queue_mutex;
    pthread_cond_t _task_condition;
    pthread_cond_t _result_condition;
    // 单例模式
    // 这两个成员再类外初始化,需注意声明顺序,保证析构顺序,垃圾回收类会自动清理资源
    static thread_pool_recycler_t thread_pool_recycler;
    static thread_pool_t<Req, Rsp> *_this;
};
// 单例模式
template <class Req, class Rsp>
thread_pool_t<Req, Rsp> *thread_pool_t<Req, Rsp>::_this{nullptr};
template <class Req, class Rsp>
typename thread_pool_t<Req, Rsp>::thread_pool_recycler_t thread_pool_t<Req, Rsp>::thread_pool_recycler{};